#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <functional>
#include <cassert>

namespace zdflog
{
// 缓冲区默认初始大小：1MB（1*1024*1024字节）
#define BUFFER_DEFAULT_SIZE (1 * 1024 * 1024)
// 缓冲区超过阈值后的增量大小：1MB
#define BUFFER_INCREMENT_SIZE (1 * 1024 * 1024)
// 缓冲区扩容策略阈值：10MB，超过此值后改变扩容方式
#define BUFFER_THRESHOLD_SIZE (10 * 1024 * 1024)

    /**
     * @brief 动态扩容的缓冲区类
     *
     * 实现了一个基于向量的动态缓冲区，通过读写索引管理数据存储，
     * 支持自动扩容以适应不同大小的数据写入需求，适用于日志等场景的数据流缓存
     */
    class Buffer
    {
    public:
        /**
         * @brief 构造函数，初始化缓冲区
         *
         * 初始容量为BUFFER_DEFAULT_SIZE（1MB），读写索引均从0开始
         */
        Buffer() : _reader_idx(0), _writer_idx(0), _v(BUFFER_DEFAULT_SIZE) {}

        /**
         * @brief 判断缓冲区是否为空
         * @return 若读写索引相等（无数据）则返回true，否则返回false
         */
        bool empty() { return _reader_idx == _writer_idx; }

        /**
         * @brief 获取当前可读数据的大小
         * @return 可读数据的字节数（写索引 - 读索引）
         */
        size_t readAbleSize() { return _writer_idx - _reader_idx; }

        /**
         * @brief 获取当前可写空间的大小
         * @return 可写空间的字节数（缓冲区总容量 - 写索引）
         */
        size_t writeAbleSize() { return _v.size() - _writer_idx; }

        /**
         * @brief 重置缓冲区
         *
         * 将读写索引均重置为0，清空缓冲区中的数据标记（实际数据未擦除）
         */
        void reset() { _reader_idx = _writer_idx = 0; }

        /**
         * @brief 与另一个缓冲区交换内容
         * @param buf 要交换的目标缓冲区
         *
         * 交换底层存储向量、读写索引，实现缓冲区数据的快速转移
         */
        void swap(Buffer &buf)
        {
            _v.swap(buf._v);                         // 交换底层存储向量
            std::swap(_reader_idx, buf._reader_idx); // 交换读索引
            std::swap(_writer_idx, buf._writer_idx); // 交换写索引
        }

        /**
         * @brief 向缓冲区写入数据
         * @param data 指向待写入数据的指针
         * @param len 待写入数据的字节数
         *
         * 确保缓冲区有足够空间后，将数据拷贝到写索引位置，并更新写索引
         * 若空间不足，会自动扩容（通过ensureEnoughSpace实现）
         */
        void push(const char *data, size_t len)
        {
            assert(len <= writeAbleSize());                // 断言：待写入长度不超过当前可写空间（实际push前会扩容，此断言可验证扩容逻辑）
            ensureEnoughSpace(len);                        // 确保有足够空间写入数据
            std::copy(data, data + len, &_v[_writer_idx]); // 拷贝数据到缓冲区
            _writer_idx += len;                            // 更新写索引
        }

        /**
         * @brief 获取可读数据的起始地址
         * @return 指向当前可读数据起始位置的常量指针
         */
        const char *begin() { return &_v[_reader_idx]; }

        /**
         * @brief 标记指定长度的数据为已读取
         * @param len 已读取数据的字节数
         *
         * 更新读索引，标记数据为已读（实际数据未擦除，仅更新索引）
         */
        void pop(size_t len)
        {
            _reader_idx += len;                 // 更新读索引
            assert(_reader_idx <= _writer_idx); // 断言：读索引不超过写索引（防止读取越界）
        }

    protected:
        /**
         * @brief 确保缓冲区有足够空间写入指定长度的数据
         * @param len 待写入数据的字节数
         *
         * 若当前可写空间不足，则根据当前缓冲区大小动态扩容：
         * - 当缓冲区大小 < 阈值（10MB）时，容量翻倍后再加上待写入长度
         * - 当缓冲区大小 >= 阈值（10MB）时，每次固定增加1MB再加上待写入长度
         */
        void ensureEnoughSpace(size_t len)
        {
            if (len <= writeAbleSize())
                return; // 若空间足够，直接返回

            /*每次增大1M大小（根据阈值判断扩容策略）*/
            size_t new_capacity;
            if (_v.size() < BUFFER_THRESHOLD_SIZE)
                new_capacity = _v.size() * 2 + len; // 小于阈值时：容量翻倍 + 待写入长度
            else
                new_capacity = _v.size() + BUFFER_INCREMENT_SIZE + len; // 大于等于阈值时：固定增加1MB + 待写入长度

            _v.resize(new_capacity); // 调整缓冲区容量
        }

    private:
        size_t _reader_idx;   // 读索引：标记当前可读数据的起始位置
        size_t _writer_idx;   // 写索引：标记当前可写入数据的起始位置
        std::vector<char> _v; // 底层存储容器：用于实际存储数据的向量
    };
}